package org.cytoscape.myapp.my_cyaction_app.internal;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.SortedSet;
import java.util.Hashtable;

import javax.swing.JOptionPane;

import org.cytoscape.event.CyEventHelper;
import org.cytoscape.model.CyColumn;
import org.cytoscape.model.CyEdge;
import org.cytoscape.model.CyIdentifiable;
import org.cytoscape.model.CyNetwork;
import org.cytoscape.model.CyNetworkFactory;
import org.cytoscape.model.CyNetworkManager;
//import org.cytoscape.data.CyAttributes;
import org.cytoscape.model.CyNode;
import org.cytoscape.application.swing.*;
import org.cytoscape.model.CyRow;
import org.cytoscape.model.CyTable;
import org.cytoscape.model.CyTableFactory;
import org.omg.CORBA.NVList;

public class MyNetwork {
	
	private CyNetworkManager ntmgr;
	private CyNetwork myNet;
	private CyEventHelper eventHelper;
	//private CyNetworkFactory networkFactory;
	private CyNetworkFactory networkFactory;
	private String Nombre= "NAME";
	
	public MyNetwork(CyNetworkFactory networkFactory, CyEventHelper eventHelper,CyNetworkManager networkManager){
		//	this.ntmgr = net;
		this.networkFactory = networkFactory;
		this.eventHelper = eventHelper; 
		this.myNet = networkFactory.createNetwork();
		this.ntmgr = networkManager;
		myNet.getRow(myNet).set(CyNetwork.NAME, "My network");
		
	}

	public void CreateNetwork(int nodos){
		
		for (int i = 0; i < nodos; i++) {
			CyNode nodo = myNet.addNode();
			myNet.getRow(nodo).set(CyNetwork.NAME, String.valueOf(i));
			
		}
		this.AddEdges();
	//	eventHelper.flushPayloadEvents();
		this.AddAttributeExample();
		
		
	}
	
	private void AddAttributeExample(){
		//CyTable table = tableFactory.createTable("New Columns", "shared name", String.class, false, false);
		
		CyTable table = myNet.getDefaultNodeTable();

		// Creo columnas 
		String edad = "edad";
		String ciudad = "ciudad"; 
		table.createColumn(edad, Integer.class, false);
		table.createColumn(ciudad, String.class, false);
		
		//creo ejemplos para luego setear estos valores en los nodos de forma aleatoria
		String[] ciudades = {"Tandil","Azul","Olavarria"};
		Integer[] edades = {15,25,50,42,45};
		//obtengo todos los nodos para luego obtener su ID y poder setear la fila correspondiente a cada nodo
		List<CyNode> lista = myNet.getNodeList();
		for (CyNode lis:lista){
			table.getRow(lis.getSUID()).set(edad, edades[(int)((Math.random()*edades.length -1)+ 1)]);
			table.getRow(lis.getSUID()).set(ciudad, ciudades[(int)((Math.random()*ciudades.length-1) + 1)]);
		}
	
	}
	
	private void AddEdges(){
		
		List<CyNode> Nodes = myNet.getNodeList();
		CyNode first = Nodes.get(0);
		for (CyNode nodo:Nodes){
			myNet.addEdge(first, nodo, false);
		}
		
	}
	
	public CyNetwork getMyNetwork(){
		return myNet;
	}

/*public Long getAtribute(String dato){
		List<String> listAux;
		CyColumn columna = null;
		CyTable table = myNet.getDefaultNodeTable();
	//	List<CyEdge> listaE = myNet.getEdgeList();
		//List<CyNode> listaN = myNet.getNodeList();
	//	List<CyRow> listaR = myNet.getDefaultNodeTable().getAllRows();
		List<CyNode> lista = myNet.getNodeList();
		/*for (CyNode lis:lista){
		//	JOptionPane.showMessageDialog(null, table.getRow(lis.getSUID()).getList(dato, null).toString());
			table.getRow(lis.getSUID());
		}*/
	//	CyRow t = listaR.get(3);
		
 	//	CyNode nodoSeleccionado = myNet.getNodeList();
		/*while(it.hasNext())
		{
			CyNode auxNode = (CyNode)it.next();
			if (auxNode.getSUID() == 15)
			{
				JOptionPane.showMessageDialog(null, auxNode.getSUID()+"   ccccccc");
				return auxNode.getSUID();
			} 
			
		}
		
	return null;
	}*/
	/*
	 * Metodo que devuelve una nueva red agrupada por atributo pasado por parametro
	 */
	
	public CyNetwork getNewNetworkByAttribute(String attribute){
		//Creo una nueva red dependiendo del atributo que ingreso
		CyNetwork networkNew = networkFactory.createNetwork();
		// Le pongo el nombre a la red
		networkNew.getRow(networkNew).set(CyNetwork.NAME, "NetworkTest");
		
	//Genero un hash donde la key es el nombre del atributo del nodo y la lista es el atributo de los nodos vecinos
		Hashtable<String,List<Object>> hashRefArcos = new Hashtable<String,List<Object>>();
		//en este metodo guardo los arcos en la hash
		hashRefArcos = guardoArcos(attribute);
		//JOptionPane.showMessageDialog(null,"visualizar hash");
	//	visualizarhash(hashRefArcos);
	
		CyColumn columnas = myNet.getDefaultNodeTable().getColumn(attribute);
		List<Object> values = columnas.getValues(columnas.getType());		
	//	JOptionPane.showMessageDialog(null,"sigue");
		ArrayList<Object> values2 = new ArrayList<Object>();
		for (Object val : values){
			if (!values2.contains(val)){
				values2.add(val);
			//	JOptionPane.showMessageDialog(null,"aca se caga");
				networkNew.getRow(networkNew.addNode()).set(CyNetwork.NAME, String.valueOf(val));
				//JOptionPane.showMessageDialog(null,hashRefArcos.get(val).size());
			}
		}
		
		//una vez generado todo combino la red con los arcos asi obtengo la red completa
		ntmgr.addNetwork(networkNew);
		generoArcos(networkNew,hashRefArcos);
		return networkNew;
	}
	//SOLO PARA VISUALIZAR LA HASH A VER SI CARGABA BIEN
	/*public List<Object>  visualizarhash(Hashtable<Object,List<Object>>hashRefArcos, Object key){
		List<Object> listaArcos =new ArrayList<Object>();
		Enumeration<Object> e = hashRefArcos.keys();
		
		while (e.hasMoreElements())
		{
			JOptionPane.showMessageDialog(null,"dentro del busco hash key "+ key+" clave de hash "+ e.nextElement());
			Object auxK = e.nextElement();
			if (auxK.equals(key)){
				JOptionPane.showMessageDialog(null,"seeee");
				listaArcos = hashRefArcos.get(e);
			}
		}
		return listaArcos;
	}*/
	
	
	
	
	
	
	//En este metodo ya tengo la red y los arcos asi que solo agrega los arcos a la red ya generada
	public void generoArcos(CyNetwork network,Hashtable<String,List<Object>> hashRefArcos){

		
	//	CyTable table = myNet.getDefaultNetworkTable();
		List<CyNode> Nodes = network.getNodeList();
		Object key;
		CyNode nodoEdad;
		for (CyNode nodoPrim:Nodes){
			key= network.getRow(nodoPrim).get(CyNetwork.NAME, String.class);
			List<Object> listaArcos = hashRefArcos.get(key);
			for (Object edades:listaArcos){
				nodoEdad = buscoNodoEnRed(network,edades);
				JOptionPane.showMessageDialog(null,"edad  "+ edades +"  key "+key);
				if ((nodoEdad != null)&&!(edades.equals(key.toString()))){
					JOptionPane.showMessageDialog(null,"son distintas");
					network.addEdge(nodoPrim, nodoEdad, false);
				}
			}
		
		}
	}
	
	//En este metodo solo buscamos si existe el nombre del nodo dentro de una red, si es asi lo devolvemos
	
	public CyNode buscoNodoEnRed(CyNetwork network,Object edad){
		CyNode aux = null;
	//	CyTable table = myNet.getDefaultNetworkTable();
		List<CyNode> Nodes = network.getNodeList();
		for (CyNode nodoPrim:Nodes){
		//	JOptionPane.showMessageDialog(null,"edad  "+edad+"  nodos  " +network.getRow(nodoPrim).get(CyNetwork.NAME, String.class) );
			if( network.getRow(nodoPrim).get(CyNetwork.NAME, String.class).equals(edad.toString())){
			//	JOptionPane.showMessageDialog(null,"entra for edad,nodos");
				aux = nodoPrim;
			 }
		}
		return aux;
	}
	
	
	//**********************************************************************************************
	
	public Hashtable<String,List<Object>> guardoArcos(String attribute){
		
		List<CyNode> lisNodoSup = myNet.getNodeList();
		CyTable table = myNet.getDefaultNodeTable();
		Hashtable<String,List<Object>> hashRefArcos = new Hashtable<String,List<Object>>();
		String aux = null;
		List<CyNode> nodosVecinos;
		List<Object> atribVecinos ;
		List<Object> listaux =new ArrayList<Object>();
		CyTable table2 = myNet.getDefaultNodeTable();
		//Obtengo el primer nodo para buscar los nodos que se relaciona
 		for (CyNode lisS:lisNodoSup){
 			atribVecinos = new ArrayList<Object>();
 			nodosVecinos = myNet.getNeighborList(lisS, CyEdge.Type.UNDIRECTED);
 			//JOptionPane.showMessageDialog(null,"nodo posta");
 			aux = table.getRow(lisS.getSUID()).getRaw(attribute).toString();
 			
 		//	JOptionPane.showMessageDialog(null,"nodo posta" + aux);
 			//Verifico que no se contenga el atributo del nodo como calve dentro de la hash
 			
 			//JOptionPane.showMessageDialog(null,"tamanio nodos vecinos  "+nodosVecinos.size());
 		
 			for (CyNode lisVecino:nodosVecinos){
 			//		JOptionPane.showMessageDialog(null,"edad nodos vecinos  "+table2.getRow(lisVecino.getSUID()).getRaw(attribute));
 					atribVecinos.add(table2.getRow(lisVecino.getSUID()).getRaw(attribute));
 				//	JOptionPane.showMessageDialog(null,"edad nodos vecinos  ");
 			}
 			if (listaux.contains(aux)){					
 			//		JOptionPane.showMessageDialog(null,"Pasa");
 					atribVecinos.addAll(hashRefArcos.get(aux));
 			}
 			//JOptionPane.showMessageDialog(null,"nodo hash   "+ aux);
 			hashRefArcos.put(aux,atribVecinos);
 			listaux.add(aux);
 		}
 	//	JOptionPane.showMessageDialog(null,"sale");
 		return hashRefArcos;
	}
	
	
	
//*******************************************************************************************************	

	
}
	